// tspcluster - Traveling Salesman Problem
// Copyright (C) 2006  Frederik Carlier
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

using System;

namespace UGent.Tsp
{
    public class SwapRandom : ISwapper
    {

        #region Constructors
        public SwapRandom(Route route)
            : this(route, 0)
        {
        }

        public SwapRandom(Route route, int count)
        {
            this.route = route;
            this.count = route.Map.CityCount;
            this.randomPermutation = new RandomPermutation();
        }
        #endregion

        #region Properties
        private int proposed;
        private int accepted;
        private int[] current;
        private int count;
        private RandomPermutation randomPermutation;

        public int ProposedMoves
        {
            get { return proposed; }
        }

        public int AcceptedMoves
        {
            get { return accepted; }
        }

        private Route route;
        public IRoute Route
        {
            get { return route; }
        }

        public int Count
        {
            get
            {
                return -1;
            }
        }
        #endregion

        #region Methods
        public void Generate()
        {
            current = randomPermutation.Next(count);
            proposed++;
        }

        public void Do()
        {
            for (int i = 0; i < count; i++)
                route[i] = current[i];

            proposed++;
        }

        public double GetDelta()
        {
            double delta = 0;

            int j;
            for (int i = 0; i < count; i++)
            {
                if (i != count - 1)
                    j = i + 1;
                else
                    j = 0;

                if (route[i] != current[i] || route[j] != current[j])
                {
                    delta -= route.GetDistance(i, j);
                    delta += route.Map.GetDistance(current[i], current[j]);
                }
            }

            return delta;
        }
        #endregion
    }
}
